package plataforma.crud.cgt;

import java.util.Collection;
import java.util.Iterator;
import java.util.Set;

import nucleo.global.ContextoSessao;

import org.springframework.beans.BeansException;
import org.springframework.transaction.annotation.Transactional;
import org.zkoss.zkplus.spring.SpringUtil;

import plataforma.autenticacao.cdp.Usuario;
import plataforma.base.cdp.ExcecaoPlataforma;
import plataforma.base.cdp.ExcecaoRegraNegocio;
import plataforma.base.cdp.IObjetoAtivoInativo;
import plataforma.base.cdp.IObjetoCancelavel;
import plataforma.base.cdp.ObjetoPagina;
import plataforma.base.cdp.ObjetoPersistente;
import plataforma.base.cdp.ResultadoPaginado;
import plataforma.crudestatico.cgd.DaoBase;
import plataforma.log.cdp.OperacaoLog;
import plataforma.log.cgt.ServiceLog;

@Transactional(rollbackFor = Exception.class)
public abstract class ServiceCrud<T extends ObjetoPersistente> {

	public abstract DaoBase<T> getNucleoDaoBase();

	public void excluir(T objeto) throws ExcecaoRegraNegocio {

		// Exclui o objeto
		getNucleoDaoBase().excluir(objeto);

	}

	public T recuperarPorId(Long id) {
		return getNucleoDaoBase().recuperarPorId(id);
	}

	public Collection<T> recuperarTodos() {
		return getNucleoDaoBase().recuperarTodos();
	}

	public void salvar(T objeto) throws Exception {
		
		OperacaoLog operacaoEscolhida = OperacaoLog.EDITAR;
		
		if(objeto.getId() == null)
			operacaoEscolhida = OperacaoLog.INCLUIR;
		
		getNucleoDaoBase().salvar(objeto);
		
		// gerar log	
		Usuario usuarioLogado = ContextoSessao.getUsuarioLogado();		
		SpringUtil.getApplicationContext().getBean(ServiceLog.class).inserirLogSimples(objeto, operacaoEscolhida,usuarioLogado);

	

	}

	public void cancelar(T objeto) throws BeansException, Exception {

		if (objeto instanceof IObjetoCancelavel) {

			IObjetoCancelavel objCast = (IObjetoCancelavel) objeto;

			objCast.setCancelado(true);
			OperacaoLog operacaoEscolhida = OperacaoLog.CANCELAR;

			getNucleoDaoBase().salvar(objeto);

			// gerar log
			Usuario usuarioLogado = ContextoSessao.getUsuarioLogado();
			
			SpringUtil.getApplicationContext().getBean(ServiceLog.class).inserirLogSimples(objeto, operacaoEscolhida,usuarioLogado);
		}

	}

	public void ativarOuInativar(T objeto) throws Exception {
		if (objeto instanceof IObjetoAtivoInativo) {

			OperacaoLog operacaoEscolhida;
			IObjetoAtivoInativo objCast = (IObjetoAtivoInativo) objeto;

			if (objCast.isAtivo()) {

				objCast.setAtivo(false);
				operacaoEscolhida = OperacaoLog.INATIVAR;

			} else {
				objCast.setAtivo(true);
				operacaoEscolhida = OperacaoLog.ATIVAR;
			}

			getNucleoDaoBase().salvar(objeto);

			// gerar log
			Usuario usuarioLogado = ContextoSessao.getUsuarioLogado();
			
					
			SpringUtil.getApplicationContext().getBean(ServiceLog.class)
					.inserirLogSimples(objeto, operacaoEscolhida,usuarioLogado);
		}

	}

	public int count() {
		return this.getNucleoDaoBase().count();
	}

	public ResultadoPaginado<T> recuperarTodosPaginado(ObjetoPagina pagina) {

		ResultadoPaginado<T> resultadoPaginado = new ResultadoPaginado<T>();

		Collection<T> listaElementos = getNucleoDaoBase()
				.recuperarTodosPaginado(pagina);
		int tamanhoTotal = getNucleoDaoBase().recuperarQteTodos(pagina);

		resultadoPaginado.setListaObjetos(listaElementos);
		resultadoPaginado.setTamanhoTotal(tamanhoTotal);

		return resultadoPaginado;
	}

	public void excluir(Set<T> objetos) throws ExcecaoRegraNegocio {

		Iterator<T> itItensSelecionados = objetos.iterator();

		while (itItensSelecionados.hasNext()) {
			T objeto = itItensSelecionados.next();
			excluir(objeto);

		}

	}

	public ResultadoPaginado<T> recuperarTodosObjetoCompleto(ObjetoPagina pagina) {

		ResultadoPaginado<T> resultadoPaginado = new ResultadoPaginado<T>();

		Collection<T> listaElementos = getNucleoDaoBase()
				.recuperarTodosObjetoCompleto(pagina);
		int tamanhoTotal = getNucleoDaoBase().recuperarQteTodos(pagina);

		// coloco as respostas no objetoResultado
		resultadoPaginado.setListaObjetos(listaElementos);
		resultadoPaginado.setTamanhoTotal(tamanhoTotal);

		return resultadoPaginado;

	}

}
